package com.mchat.ratelimit.strategy.impl;

import com.mchat.ratelimit.dto.BaseDTO;
import com.mchat.ratelimit.strategy.AbstractRateLimitStrategy;
import com.mchat.ratelimit.strategy.StrategyEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
import reactor.core.publisher.Mono;

import java.time.Duration;
@RequiredArgsConstructor
public class FixWindowRateLimitStrategy extends AbstractRateLimitStrategy {
    private final ReactiveStringRedisTemplate redisTemplate;
    @Override
    public <T extends BaseDTO> Mono<Boolean> reachRateLimit(T dto) {
        StringBuilder key = dto.getKey();
        long windowSize = dto.getSecond(); // 窗口大小，单位秒
        // 限流的最大请求次数

        // 计算当前时间的秒值,用于对齐窗口
        long currentTime = System.currentTimeMillis()/1000;
        // 计算当前时间所属窗口的起始时间
        long windowStartTime = currentTime - (currentTime % (windowSize));

        // 构建 Redis 中使用的 key
        key.append(':').append(windowStartTime);
        return redisTemplate.opsForValue().increment(key.toString()).flatMap(count->{
            //如果是第一次读取则设置过期时间
            if (count==1){
                return redisTemplate.expire(key.toString(), Duration.ofSeconds(windowSize*2)).thenReturn(count>dto.getCount());
            }
            return Mono.just(count>dto.getCount());
        });


    }
    @Override
    protected String getStrategyName() {
        return StrategyEnum.FIX_WINDOW;
    }
}